package org.epanetgrid.otimizacao.ag;

import org.jheuristics.Individual;
import org.jheuristics.ga.GAConfig;
import org.jheuristics.ga.GAStatus;
import org.jheuristics.ga.operators.Probability;
import org.jheuristics.ga.operators.Reproductor;
import org.jheuristics.ga.operators.reproductors.GensListOnePointXOver;
import org.jheuristics.ga.operators.reproductors.funcionalidades.IListXOver;

/**
 * Classe respons�vel por efetuar o Crossver Direcionado (ver especifica��o para mais detalhes)
 * @author Vin�cius Ferraz Campos, vinicius.ferraz@gmail.com
 *
 */
public class CrossverDirecionado extends GensListOnePointXOver {

	/**
	 *
	 * @param probability Probabilidade de efetuar o cruzamento
	 * @param maxTryOuts M�ximo de tentativas
	 * @param listXOver Classe respons�vel por efetuar o cruzamento (editor de funcionalidades)
	 */
	public CrossverDirecionado(Probability probability, int maxTryOuts, IListXOver listXOver) {
		super(probability, maxTryOuts, listXOver);
	}

	/**
	 * 
	 * @param decoretedReproductor Reprodutor
	 * @param probability Probabilidade de efetuar o cruzamento
	 * @param tryOuts M�ximo de tentativas
	 * @param listXOver Classe respons�vel por efetuar o cruzamento (editor de funcionalidades)
	 */

	public CrossverDirecionado(Reproductor decoretedReproductor, Probability probability, int tryOuts, IListXOver listXOver) {
		super(decoretedReproductor, probability, tryOuts, listXOver);
	}


	/* (non-Javadoc)
	 * @see org.jheuristics.ga.operators.Reproductor#reproduce(org.jheuristics.Individual[], org.jheuristics.ga.GAStatus, org.jheuristics.ga.GAConfig)
	 */
	public Individual[] reproduce(Individual[] parents, GAStatus status, GAConfig config) {
    	if (null == parents) {
			// TODO: ERROR MSG
            throw new NullPointerException();
    	}
    	if (2 > parents.length) {
			// TODO: ERROR MSG
    		throw new IllegalArgumentException();
    	}
    	for (int i = 0; i < 2; i++) {
    		if (null == parents[i]) {
    			// TODO: ERROR MSG
                throw new NullPointerException();
    		}
    	}
        if (null == config) {
			// TODO: ERROR MSG
            throw new NullPointerException();
        }
        if (null != getDecoratedReproductor()) {
        	int erroParent1 = ((SimpleFitness) parents[0].getFitness()).getIntervaloDeErro();
        	int erroParent2 = ((SimpleFitness) parents[1].getFitness()).getIntervaloDeErro();
        	if (3 > erroParent1 || 3 > erroParent2 || erroParent1 == erroParent2) {
        		return decorate(parents, status, config);
        	}
        }
    	Individual[] result = null;
    	StringBuffer buffer = new StringBuffer();
    	buffer.append("Verificando probabilidade de cruzamento Direcionado:");
    	buffer.append("\n");
    	if (getProbability().check(status, config)) {
    		buffer.append("Cruzamento Direcionado será efetuado");
    		buffer.append("\n");
    		logger.debug(buffer);
            return xover(parents, status, config);
    	}else {
    		buffer.append("Cruzamento Direcionado Não será efetuado");
    		buffer.append("\n");
    		logger.debug(buffer);
    	}
    	if (null == result) {
    		result = new Individual[] {parents[0], parents[1]};
    	}
		return result;
	}

	/* (non-Javadoc)
	 * @see org.jheuristics.ga.operators.reproductors.GensListOnePointXOver#chooseXOverPoints(org.jheuristics.Individual, org.jheuristics.Individual, org.jheuristics.ga.GAStatus, org.jheuristics.ga.GAConfig)
	 */
	protected int[] chooseXOverPoints(Individual parent1, Individual parent2, GAStatus status, GAConfig config) {
    	int erroParent1 = ((SimpleFitness) parent1.getFitness()).getIntervaloDeErro();
    	int erroParent2 = ((SimpleFitness) parent2.getFitness()).getIntervaloDeErro();
		return new int[] {Math.min(erroParent1, erroParent2) - 3};
	}

}
